home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr53 / pctv4n_1.zip / MAKETEMP.ASM < prev    next >
Assembly Source File  |  1993-06-10  |  12KB  |  404 lines

  1. ;****************************************************************
  2. ; Create Temporary File with a Unique Name.
  3. ; Copyright (c) 1993 FM de Monasterio.  All Rights Reserved.
  4. ;
  5. ;   These procedures may be distributed freely and used in
  6. ;   application programs with acknowledgement, but may not
  7. ;   be sold in unit form.
  8. ;
  9. ; Written for OPTASM 1.65
  10. ;----------------------------------------------------------------
  11. ; Input:
  12. ;    DS:DX -> ASCIIz backslash-ending path (e.g."D:\TMP\DATA\",0)
  13. ;       CX = Attributes: 0=Normal, 1=ReadOnly, 2=Hidden, 4=System
  14. ;                        20h=Archive, or their ORed combinations
  15. ; Output:
  16. ;      Success: CF=0, AX=handle, 13-byte TempFile field at end
  17. ;      Failure: CF=1, AX=error code: 03h=Path not found
  18. ;                                    04h=Too many open files
  19. ;                                    05h=Access denied
  20. ;                                    50h=Unique name not found
  21. ;                                    ??h=Disk critical error code
  22. ; Alters: AX, Flags (DF=0)
  23. ;****************************************************************
  24. _CODE        segment    para public '_code'
  25.         assume    cs:_code, ds:nothing, es:nothing
  26.  
  27.         PUBLIC    TempFile
  28.  
  29.      ; LOCAL DATA - Even alignment of words and strings
  30. EVEN
  31. Int24Vect    LABEL    DWORD
  32. Int24Offs    DW    ?            ; old INT 24h address
  33. Int24Segm    DW    ?
  34.  
  35. TempAddr    LABEL    DWORD            ; address of name field
  36. TempOffs    DW    ?            ; in caller's DS segment
  37. TempSegm    DW    ?
  38.  
  39.      ; Temporary ASCIIz filepath
  40.  
  41. TempBuff    DB    120 dup (?)        ; TempPath buffer
  42. TempName    DB    8   dup (?)        ; 8-character name
  43.         DB    0            ; ASCIIz mark
  44.  
  45. TempDisk    DB    0            ; TempPath drive
  46.  
  47. TempAttr    DW    ?            ; file attribute mask
  48. TempTail    DW    ?            ; path-end pointer storage
  49. TempDate    DW    ?            ; date stamp
  50. TempTime    DW    ?            ; time stamp
  51.  
  52. Int24Flag    DB    0            ; 0=no error, 1=crit error
  53.  
  54. ;----------------------------------------------------------------
  55. EVEN
  56. TempFile PROC FAR
  57.         push    ES            ; save used registers
  58.         push    DS
  59.         push    DI
  60.         push    SI
  61.         push    DX
  62.         push    BX
  63.         push    CX
  64.  
  65.         mov    SI,DX            ; save TempPath offset
  66.  
  67.     ; Check DOS version to decide whether to use function 5Ah
  68.     ; (MS-DOS 3.x through 4.x) or 5Bh (MS-DOS 5A/B and 6A).
  69.     ;
  70.     ; Use first function 3306h (get 'true' MS-DOS version) to
  71.     ; exclude MS-DOS 5+ is executing under SETVER (or another
  72.     ; TSR) asserting a different version via fxn 30h:
  73.     ;
  74.     ; BH= Minor, BL= Major version
  75.     ; DL= (bits 0-2) Revision no. (Microsoft uses "A"=0, "B"=1)
  76.     ; CF= Clear in Revision 5A, set in Revision 5B
  77.     ; DH= Memory location flag bit 3=1: DOS in ROM, else in RAM
  78.     ;            flag bit 4=1: DOS in HMA, else in 640K
  79.  
  80.         xor    BX,BX            ; MS-DOS 5+ changes BX/DX
  81.         mov    AX,3306h        ; fxn get true MS-DOS ver
  82.         int    21h
  83.  
  84.     ; Because MS-DOS 5B sets CY, the CF status cannot be used to
  85.     ; exclude DR-DOS 5+, which also sets CY upon fxn 3306h.    Use
  86.     ; instead BX, which is modified by MS-DOS 5+ (but not by MS-
  87.     ; or PC-DOS 3 through 4, or by DR-DOS 5 or 6).
  88.     ;
  89.         cmp    BX,5            ; MS-DOS 5?
  90.         je    TempDosBug        ; yes, use fxn 5Bh
  91.  
  92.     ; Next comp assumes MS-DOS 6 is still buggy - Delete, if not
  93.  
  94.         cmp    BX,6            ; assume MS-DOS 6 is
  95.         je    TempDosBug        ; also buggy but that
  96.                         ; a future DOS 7+ is not
  97.     ;
  98.     ; Execute function 5Ah and return
  99.     ;
  100. TempDosOk:    mov    AH,5Ah            ; fxn create temp file
  101.         mov    DX,SI            ; CX and DS unchanged
  102.         int    21h
  103.         jmp    TempFileRetf        ; pop and return (CF safe)
  104.  
  105. ;
  106. ; ** Function 5Ah buggy - Implement alternative procedure **
  107. ;
  108. EVEN
  109. TempDosBug:    cld                ; strings forward
  110.         push    CS
  111.         pop    ES
  112.     assume    es:_code
  113.  
  114.         mov    es:[TempAttr],CX    ; save attribute mask
  115.         mov    es:[TempSegm],DS    ; and filepath segment
  116.                         ; (SI has path offset)
  117.     ;
  118.     ; Copy TempPath to local buffer
  119.     ;
  120.         mov    DI,offset TempBuff    ; ES:DI -> local buffer
  121.         mov    AX,ds:[SI]        ; DS:SI -> TempPath
  122.         mov    CX,120            ; maximum buffer length
  123.         cmp    AH,":"            ; drive spec given?
  124.         jne    TempPathByte        ; no, skip
  125.         mov    es:[TempDisk],AL    ; else update INT-24h ISR
  126. EVEN
  127. TempPathByte:    lodsb                ; get TempPath character
  128.         or    AL,AL            ; reached null marker?
  129.         jz    TempPathNull        ; yes, skip over
  130.         stosb                ; else save in buffer and
  131.         loop    TempPathByte        ; get next if within bounds
  132.  
  133.         stc                ; too long, signal error and
  134.         mov    AX,3            ; return Path_Not_Found code
  135.         jmp    TempFileRetf
  136.  
  137.     ;
  138.     ; Found end of ASCIIz path - Save pointers
  139. EVEN    ;
  140. TempPathNull:    mov    DX,CS
  141.         mov    DS,DX            ; restore DS addressability
  142.     assume    ds:_code
  143.         dec    SI            ; adjust ptr to last byte
  144.         mov    [TempTail],DI        ; save local tail pointer
  145.         mov    [TempOffs],SI        ; offset for appending name
  146.  
  147.     ;
  148.     ; Save and hook Critical Error handler    ** PRESERVE DX=CS **
  149.     ;
  150.         mov    AX,3524h        ; fxn get INT 24h vector
  151.         int    21h
  152.         mov    [Int24Offs],BX        ; offset
  153.         mov    [Int24Segm],ES        ; segment
  154.  
  155.         mov    ES,DX
  156.     assume    es:_code
  157.         mov    AX,2524h        ; fxn set INT 24h vector
  158.         mov    DX,offset Int24Temp    ; ES:DX -> new handler
  159.         int    21h
  160.  
  161.     ;
  162.     ; == Reentry point: Calculate new time/date stamp ==
  163. EVEN    ;
  164. TempFileName:    call    GetDate            ; AX=(((Y-1980)*512)+M*32)+D
  165.         mov    [TempDate],AX        ; store packed date
  166.         call    GetTime            ; AX=((h*4096)+m*64)+s
  167.         mov    BX,32            ; init bit rotation counter
  168.                         ; * PRESERVE BX UNTIL DONE *
  169.     ;
  170.     ; == Reentry point: Old stamp rotation loop ==
  171. EVEN    ;
  172. TempFileLoop:    mov    DI,offset TempName    ; ES:DI -> name chars 1-4
  173.         mov    [TempTime],AX        ; store packed time
  174.         call    Word2Hex        ; write first half stamp
  175.  
  176.         mov    DI,offset TempName[4]    ; ES:DI -> name chars 5-8
  177.         mov    AX,[TempDate]        ; read packed date
  178.         call    Word2Hex        ; write second half stamp
  179.  
  180.     ;
  181.     ; Append tentative filename to TempPath string
  182.     ;
  183.         mov    SI,offset TempName    ; DS:SI -> start of name
  184.         mov    DI,[TempTail]        ; ES:DI -> end of path
  185.         mov    CX,4            ; name to append (words)
  186.         rep    movsw
  187.  
  188.     ;
  189.     ; Attempt to create new file with current name
  190.     ;
  191.         mov    AH,5Bh            ; fxn create new file
  192.         mov    CX,[TempAttr]        ; attribute mask
  193.         mov    DX,offset TempBuff    ; DS:DX -> "unique" name
  194.         int    21h
  195.  
  196.         mov    DX,AX            ; save handle/error code
  197.         jc    TempFileFail        ; CF=1, DOS error in AX
  198.  
  199.         mov    AL,[Int24Flag]        ; get critical-flag status
  200.         or    AL,AL            ; error? (ORing sets CF=0)
  201.         jz    TempFileExit        ; no, return success
  202.  
  203. TempFileQuit:    push    DX            ; save error code in stack
  204.         stc                ; reset CF to signal error
  205.         jmp    short TempFileCrit
  206.  
  207.     ;
  208.     ; *** File creation error
  209. EVEN    ;
  210. TempFileFail:    cmp    AX,50h            ; File_Exists error code?
  211.         jne    TempFileQuit        ; no, return failure
  212.         dec    BX            ; all 32 bits rotated?
  213.         jz    TempFileName        ; yes, make new stamp
  214.  
  215.     ;
  216.     ; 32-bit ROL date/time stamp by 1 bit
  217.     ;
  218.         mov    DX,[TempDate]
  219.         mov    AX,[TempTime]        ; get old date:time dword
  220.  
  221.         shl    DX,1            ;  0-> DX b0... DX b15-> CF
  222.         rcl    AX,1            ; CF-> AX b0... AX b15-> CF
  223.         adc    DX,0            ; CF-> DX b0
  224.         mov    [TempDate],DX        ; store rotated date
  225.         jmp    short TempFileLoop    ; and try again
  226.  
  227.     ;
  228.     ; *** Successful temporary file creation:
  229.     ;    Return the 8-character unique name
  230. EVEN    ;
  231. TempFileExit:    push    DX            ; save file handle
  232.         mov    CX,4            ; name to append (words)
  233.         mov    SI,offset TempName    ; DS:SI -> unique name
  234.         les    DI,[TempAddr]        ; ES:DI -> caller's field
  235.         rep    movsw
  236.  
  237.     ;
  238.     ; Restore INT-24h vector
  239.     ;
  240. TempFileCrit:    pushf                ; save CF status
  241.         mov    AX,2524h        ; fxn set INT 24h vector
  242.         lds    DX,[Int24Vect]        ; to old address in DS:DX
  243.         int    21h
  244.  
  245.         popf                ; restore CF and get back
  246.         pop    AX            ; the handle or error code
  247.  
  248.     ;
  249.     ; Restore registers and return to caller
  250.     ;
  251. TempFileRetf:    pop    CX            ; and restore registers
  252.         pop    BX
  253.         pop    DX
  254.         pop    SI
  255.         pop    DI
  256.         pop    DS
  257.         pop    ES
  258.         retf                ; far return to caller
  259. TempFile ENDP
  260.  
  261.  
  262. ;****************************************************************
  263. ; Local INT-24h Handler (DOS critical error)
  264. ; On entry:
  265. ;    AH : bit 7 = 0 if disk I/O error
  266. ;    DI : lower byte = error code (upper byte undefined)
  267. ;    BP:SI-> device header structure containing info about
  268. ;        the device on which the error took place.
  269. ; On exit:
  270. ;    AL = value specifying action that DOS should take
  271. ;        depending on what is allowed (AH bits 5-3).
  272. ;****************************************************************
  273.         assume    ds:nothing
  274. EVEN
  275. Int24Temp PROC FAR
  276.         test    AH,80h            ; disk error?
  277.         jnz    Int24Exit        ; no, exit
  278.         cmp    cs:[TempDisk],0        ; drive letter specified?
  279.         je    Int24Disk        ; no, assume TempPath disk
  280.  
  281.         add    AL,"A"            ; get 0=A, 1=B, etc
  282.         cmp    AL,cs:[TempDisk]    ; is this the right drive?
  283.         je    Int24Disk        ; yes, handle error
  284.         sub    AL,"A"            ; else let DOS handle it
  285. Int24Exit:    jmp    cs:[Int24Vect]
  286.  
  287.     ;
  288.     ; Drive error
  289. EVEN    ;
  290. Int24Disk:    mov    AX,DI            ; save critical error code
  291.         mov    cs:[Int24Flag],AL    ; from lower byte of DI
  292.         xor    AX,AX            ; and tell DOS to ignore
  293.         iret                ; error (or terminate fxn)
  294. Int24Temp ENDP
  295.  
  296.  
  297. ;****************************************************************
  298. ; Pack date in DOS-file stamp format
  299. ;    bit 09-15: Year (0-119 offset from 1980) * 512
  300. ;    bit 05-08: Month (1-12) * 32
  301. ;    bit 00-04: Day (1-31)
  302. ;
  303. ; Input:  None
  304. ; Output: AX = [([Year-1980]*512)+Month*32]+Day
  305. ; Alters: AX BX CX DX
  306. ;****************************************************************
  307.         assume    ds:_code
  308. EVEN
  309. GetDate PROC NEAR
  310.         mov    AH,2Ah            ; fxn get current date
  311.         int    21h            ; CX=YY, DH=MM, DL=DD
  312.         mov    AX,CX            ; get AX=1980 through 2099
  313.         sub    AX,1980            ; and make offset from 1980
  314.         mov    CL,1            ; shift reps for (YY*256)*2
  315.         jmp    short GetStamp        ; and chain into next proc
  316. GetDate ENDP
  317.  
  318.  
  319. ;****************************************************************
  320. ; Pack time in quasi-DOS-file format
  321. ;        bits 12-15: hours (0-12) * 4096
  322. ;        bits 06-10: minutes (0-59) * 64
  323. ;        bits 00-05: seconds (0-59)
  324. ;
  325. ; instead of DOS format
  326. ;        bit 11-15: hours (0-23) * 2048
  327. ;        bit 05-10: minutes (0-59) * 32
  328. ;        bit 00-04: seconds (0-29) in 2-second intervals
  329. ;
  330. ; Input:  None
  331. ; Output: AX = [(Hour*4096)+Minute*64]+Second
  332. ; Alters: AX BX CX DX
  333. ;****************************************************************
  334.         assume    ds:_code
  335. EVEN
  336. GetTime PROC NEAR
  337.         mov    AH,2Ch            ; fxn get current time
  338.         int    21h            ; CH=hh, CL=mm, DH=ss
  339.         mov    AL,CH            ; copy 0-23 hour
  340.         sub    AL,12            ; AM or PM?
  341.         jnc    GetHour            ; PM, keep difference
  342.         mov    AL,CH            ; else AM
  343. EVEN
  344. GetHour:    cbw                ; AX = 0-12 h
  345.         mov    DL,DH            ; DL = 0-59 s
  346.         mov    DH,CL            ; DH = 0-59 m
  347.         shl    DH,1            ; DH = m*2
  348.         mov    CL,4            ; shift reps for (h*256)*16
  349.  
  350.     ;
  351.     ; Repack data in stamp format
  352. EVEN    ;
  353. GetStamp:    xchg    AH,AL            ; fast Y*256 or h*256
  354.         shl    AX,CL            ; (Y-1980)*512 or h*4096
  355.         xor    BX,BX            ; zero register
  356.         xchg    BL,DH            ; DX = D or s, BX=M or m*2)
  357.         mov    CL,5            ; get times-32 shift reps
  358.         shl    BX,CL            ; BX = M*32 or m*64
  359.         add    AX,BX
  360.         add    AX,DX            ; AX=(h*4096)+(m*64)+s or
  361.         retn                ; AX=(Y-1980)*512+M*32+D
  362. GetTime ENDP
  363.  
  364.  
  365. ;****************************************************************
  366. ; Convert 16-bit binary to 4-ASCII hexadecimals and store as ES:DI
  367. ;
  368. ; Input:  AX = binary number (word), ES:DI -> memory offset
  369. ; Output: None
  370. ; Alters: AX CX DX DI
  371. ;****************************************************************
  372.         assume    ds:_code, es:_code
  373. EVEN
  374. Word2Hex PROC NEAR
  375.         std                ; set to fill backwards
  376.         add    DI,3            ; (3+1) digits to fill
  377.         mov    CX,4            ; in 4 nibbles
  378.  
  379.     ;
  380.     ; ** PRESERVE [BX] **
  381. EVEN    ;
  382. Word2Hex1:    mov    DX,AX            ; save accumulator
  383.         and    AX,000Fh        ; read LSN
  384.         cmp    AL,9            ; 0Ah-0Fh range?
  385.         ja    Word2Hex2        ; yes
  386.         add    AL,"0"            ; no, make ASCII digit
  387.         jmp    short Word2Hex3        ; and store it
  388.  
  389. Word2Hex2:    add    AL,55            ; else make ASCII letter
  390. Word2Hex3:    stosb                ; and store it
  391.         mov    AX,DX
  392.         ror    AX,1            ; rotate nibble
  393.         ror    AX,1            ; ** PRESERVE [CX] **
  394.         ror    AX,1
  395.         ror    AX,1
  396.         loop    Word2Hex1        ; convert next nibble
  397.         cld                ; clear DF
  398.         retn
  399. Word2Hex ENDP
  400.  
  401.  
  402. _CODE        ends
  403.         END
  404.